package top.superflow.core.metadata

import org.apache.commons.lang3.builder.ToStringBuilder
import top.superflow.core.metadata.category.Category
import top.superflow.core.metadata.exception.MetadataException
import top.superflow.core.metadata.id.Identifier
import top.superflow.core.semantic.{SemanticData, SemanticUtils}

import scala.collection.mutable.ListBuffer
import scala.collection.{Map, Set}


trait OldMetadata {
  
  private val elements  = Map[String, MetadataElement]()
  
  private var promisedSemantics : Map[SemanticData, String] = _
  
  
  def getIdentifier : Identifier = null
  
  def getCategory : Category
  
  
  private def initPromisedSemantics {
    if(promisedSemantics == null){
      promisedSemantics == Map[SemanticData, String]()
      for((key, element) <- elements){
      }
    }
  }
  def getPromisedSemantics : Set[SemanticData] = {
    initPromisedSemantics
    
    promisedSemantics.keySet
  }
  
  def getMetadata(semantic : SemanticData) : String = {
    val element = getMetadataElement(semantic)
    
    getMetadata(element)
  }
  
  def getMetadataElement(semantic : SemanticData) : MetadataElement = ???
  
  def getPromisedSemantic(semantic : SemanticData) : SemanticData = {
    if(semantic == null) {
      return null
    }
    
    val matchedSemantics = ListBuffer[SemanticData]()
    for(supportedSemantic <- getPromisedSemantics){
      if(SemanticUtils.equals(supportedSemantic, semantic)){
        matchedSemantics += supportedSemantic
      }
    }
      
    matchedSemantics.size match {
      case suitableCount if(suitableCount > 1) => {
        throw new MetadataException("For the semantic " + ToStringBuilder.reflectionToString(semantic) + ", there are two corresponding metadata, please update the semantic propery to match only one")
      }
      case suitableCount if(suitableCount == 0) => {
        return null
      }
      
      case _ => {
        matchedSemantics.apply(0)
      }
    }
  }
  
  private def isPromised(semantic : SemanticData) : Boolean = {
    val foundPromisedSemantic = getPromisedSemantic(semantic)
    
    foundPromisedSemantic != null
  }
  
  def getMetadata(name : String) : String = {
    val element = getMetadataElement(name)
    
    getMetadata(element)
  }
  
  def getMetadataElement(name : String) : MetadataElement = {
    elements.apply(name)
  }
  
  private def getMetadata(element : MetadataElement) : String = {
    if(element == null){
      null
    }else{
      element.getValue()
    }
  }
  
  protected def getBySemantic(semantic : SemanticData) : MetadataElement = {
    if(semantic == null){
      return null
    }
    
    val metedataElement = getMetadataFromPromised(semantic)
    if(metedataElement != null){
      return metedataElement;
    }
    
    searchBySemantic(semantic ) 
  }
  
  
  protected def searchBySemantic(semantic : SemanticData) : MetadataElement = ???
  
  
  protected def getMetadataFromPromised(semantic : SemanticData) : MetadataElement= ???
  
  protected def getBySemantic(semanticWords : String) : MetadataElement = {
    var semantic = getSemanticByKeyWords(semanticWords)
    var metadataElement = getBySemantic(semantic)
    if(metadataElement != null){
      return metadataElement
    }
    
    semantic = getSemanticBySynonym(semanticWords)
    getBySemantic(semantic)
  }
  
  protected def getSemanticByKeyWords(semanticWords : String) : SemanticData = {
    var semantic = SemanticUtils.createKeyWordSemantic(semanticWords)
    
    repalcePromisedOneIfFound(semantic)
  }
  
  protected def getSemanticBySynonym(semanticWords : String) : SemanticData = {
    var semantic = SemanticUtils.createSynonymSemantic(semanticWords)
    
    repalcePromisedOneIfFound(semantic)
  }
  
  private def repalcePromisedOneIfFound(semantic : SemanticData) : SemanticData = {
    var foundPromisedSemantic = getPromisedSemantic(semantic)
    
    if(foundPromisedSemantic != null) {
      foundPromisedSemantic
    }else{
      semantic
    }
  }
  
//  private def isSemanticSatisfied : Boolean = {
//    val supportedSemantics = this.getSupportedSemantics
//    
//    if(supportedSemantics == null || supportedSemantics.size == 0){
//      return true
//    }
//    
//    for(semantic <- supportedSemantics){
//      if(!isSemanticSupported(elements.keySet, semantic)){
//        return false
//      }
//    }
//    
//    true
//  }
//  
//  private def isSemanticSupported(metadataNames : Set[String], semantic : SemanticData) : Boolean = {
//    if(semantic == null){
//      return false
//    }
//    
//    for(metadataName <- metadataNames){
//      if(SemanticUtils.isSemanticEqual(metadataName, semantic)){
//        return true
//      }
//    }
//    
//    false
//  }
  
}

